package com.tencent.wxpay.business;

import com.tencent.wxpay.businessListener.BaseResultListener;
import com.tencent.wxpay.common.Configure;
import com.tencent.wxpay.common.Signature;
import com.tencent.wxpay.common.Util;
import com.tencent.wxpay.common.XMLParser;
import com.tencent.wxpay.common.report.ReporterFactory;
import com.tencent.wxpay.common.report.protocol.ReportReqData;
import com.tencent.wxpay.common.report.service.ReportService;
import com.tencent.wxpay.protocol.request.OrderQueryReqData;
import com.tencent.wxpay.protocol.response.OrderQueryResData;
import com.tencent.wxpay.service.OrderQueryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 订单查询服务
 */
public class OrderQueryBusiness {

    private static final Logger logger = LoggerFactory.getLogger(OrderQueryBusiness.class);

    /**
     * 运行订单查询服务
     * @param orderQueryReqData 这个数据对象里面包含了API要求提交的各种数据字段
     * @param resultListener 业务逻辑可能走到的结果分支，需要商户处理
     * @return orderQueryResData 返回的数据对象
     * @throws Exception
     */
    public static OrderQueryResData run(OrderQueryReqData orderQueryReqData, BaseResultListener<OrderQueryResData> resultListener) throws Exception {
        //--------------------------------------------------------------------
        //构造请求“退款API”所需要提交的数据
        //--------------------------------------------------------------------
        OrderQueryService orderQueryService = new OrderQueryService();
        String outTradeNo = orderQueryReqData.getOut_trade_no();
        //接收API返回值
        String orderQueryServiceResponseString;
        // API调用开始时间
        long costTimeStart = System.currentTimeMillis();
        // 发送请求
        orderQueryServiceResponseString = orderQueryService.request(orderQueryReqData);
        // API调用结束时间
        long costTimeEnd = System.currentTimeMillis();
        // API请求耗费时间
        long totalTimeCost = costTimeEnd - costTimeStart;
        logger.info("订单查询接口，【订单号："+outTradeNo+"】请求总耗时：" + totalTimeCost + "ms");
        //打印回包数据
        logger.info("订单查询接口,【订单号："+outTradeNo+"】 回包数据:");
        logger.info(orderQueryServiceResponseString);

        //将从API返回的XML数据映射到Java对象
        OrderQueryResData orderQueryResData = (OrderQueryResData) Util.getObjectFromXML(orderQueryServiceResponseString, OrderQueryResData.class);
        //是否发送统计请求
        if(Configure.isReport()) {
            ReportReqData reportReqData = new ReportReqData(
                orderQueryResData.getDevice_info(),
                Configure.ORDER_QUERY_API,
                (int) (totalTimeCost),//本次请求耗时
                orderQueryResData.getReturn_code(),
                orderQueryResData.getReturn_msg(),
                orderQueryResData.getResult_code(),
                orderQueryResData.getErr_code(),
                orderQueryResData.getErr_code_des(),
                orderQueryResData.getOut_trade_no(),
                Configure.getIP()
            );
            // refund+report总耗时
            long timeAfterReport;
            // 判断是否异步发送
            if (Configure.isUseThreadToDoReport()) {
                ReporterFactory.getReporter(reportReqData).run();
                timeAfterReport = System.currentTimeMillis();
                logger.info("【订单号："+outTradeNo+"】orderQuery+report总耗时（异步方式上报）：" + (timeAfterReport - costTimeStart) + "ms");
            } else {
                ReportService.request(reportReqData);
                timeAfterReport = System.currentTimeMillis();
                logger.info("【订单号："+outTradeNo+"】orderQuery+report总耗时（同步方式上报）：" + (timeAfterReport - costTimeStart) + "ms");
            }
        }
        // API通信失败
        if (orderQueryResData == null || orderQueryResData.getReturn_code() == null) {
            logger.error("【订单查询失败】【订单号："+outTradeNo+"】关闭订单请求逻辑错误，请仔细检测传过去的每一个参数是否合法，或是看API能否被正常访问");
            resultListener.onFailByReturnCodeError(orderQueryResData);
            return orderQueryResData;
        }
        // API通信成功，但调用出错，可能签名失败或参数格式校验错误
        if (orderQueryResData.getReturn_code().equals("FAIL")) {
            ///注意：一般这里返回FAIL是出现系统级参数错误，请检测Post给API的数据是否规范合法
            logger.error("【订单查询失败】【订单号："+outTradeNo+"】关闭订单接口系统返回失败，请检测Post给API的数据是否规范合法");
            resultListener.onFailByReturnCodeFail(orderQueryResData);
            return orderQueryResData;
        } else {
            // API通信成功，调用接口成功，有返回数据,但业务不一定执行成功
            logger.info("订单查询接口【订单号："+outTradeNo+"】成功返回数据");
            //--------------------------------------------------------------------
            //收到API的返回数据的时候得先验证一下数据有没有被第三方篡改，确保安全
            //--------------------------------------------------------------------
            if (!Signature.checkIsSignValidFromResponseString(orderQueryServiceResponseString)) {
                logger.error("【订单查询失败】【订单号："+outTradeNo+"】关闭订单请求API返回的数据签名验证失败，有可能数据被篡改了");
                resultListener.onFailBySignInvalid(orderQueryResData);
                return orderQueryResData;
            }

            if (orderQueryResData.getResult_code().equals("FAIL")) {
                logger.error("【订单查询失败】【订单号："+outTradeNo+"】");
                logger.error("错误码：" + orderQueryResData.getErr_code());
                logger.error("错误信息：" + orderQueryResData.getErr_code_des());
                //退款失败时再怎么延时查询退款状态都没有意义，这个时间建议要么再手动重试一次，依然失败的话请走投诉渠道进行投诉
                resultListener.onFail(orderQueryResData);
            } else {
                //退款成功
                orderQueryResData.setCoupons(XMLParser.getOrderCouponList(orderQueryServiceResponseString));
                logger.info("【订单查询成功】【订单号："+outTradeNo+"】");
                resultListener.onSuccess(orderQueryResData);
            }
        }
        return orderQueryResData;
    }
}
